{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "skip"
    }
   },
   "source": [
    "# Demonstration of boolean functions and ipywidgets\n",
    "\n",
    "This notebook demonstrates the boolean functions in the logic tools overlay used with iPython Widgets.\n",
    "\n",
    "\n",
    "## Slideshow\n",
    "\n",
    "This notebook is intended to be run as a slideshow, but can also be run as a regular notebook. \n",
    "\n",
    "Go to View > Cell Toolbar > Slideshow to see the *Slideshow options* for each cell. From here you can select which slides will be included or excluded from the presentation. \n",
    "\n",
    "Code cells can be executed from the slideshow view by clicking the code cell, and pressing CTRL + ENTER\n",
    "\n",
    "\n",
    "## Instructions to run the demo:\n",
    "\n",
    "* Before entering the slideshow view, click Cell > Run All to execute all the code in the notebook. \n",
    "\n",
    "You can browse through the notebook and example the code that us used to build the demonstration.\n",
    "\n",
    "In slideshow mode, use the cursor keys (left right) to navigate through the presentation\n",
    "\n",
    "* Press Alt + r to enter the slideshow and hide this view. (Exit slideshow mode with the same keys Alt + r)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "slideshow": {
     "slide_type": "skip"
    }
   },
   "outputs": [],
   "source": [
    "import ipywidgets as widgets\n",
    "from ipywidgets import interact\n",
    "from IPython.display import display\n",
    "\n",
    "from pynq.overlays.logictools import LogicToolsOverlay\n",
    "logictools_olay = LogicToolsOverlay('logictools.bit') # Download the logictools overlay"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "slideshow": {
     "slide_type": "skip"
    }
   },
   "outputs": [],
   "source": [
    "def update_boolean_generator(sender):\n",
    "    led = output.value.replace(\"E\", \"\") # Change \"LED\" to \"LD\"\n",
    "    led = led.replace(\"NOT \", \"~\") # Replace the text \"NOT\" with the \"~\" (NOT operator in Python)\n",
    "    \n",
    "    logic = []\n",
    "    for i in [logic0.value, logic1.value, logic2.value]:\n",
    "        if i is 'AND' :\n",
    "            logic.append('&')\n",
    "        elif i is 'OR' :\n",
    "            logic.append('|')\n",
    "        elif i is 'XOR' :\n",
    "            logic.append('^')\n",
    "    \n",
    "    inputs = []\n",
    "    for i in [input0.value, input1.value, input2.value, input3.value]:\n",
    "        if i is not '-' :\n",
    "            i = i.replace(\"NOT \", \"~\") \n",
    "            inputs.append(i)\n",
    "            \n",
    "    # Build logic function\n",
    "    # Assumes inputs[0] always exists\n",
    "    function = led + '=' + inputs[0]\n",
    "\n",
    "    for i, j in zip(logic, inputs[1:4]):\n",
    "        function = function + i + j\n",
    "\n",
    "    # Apply the function to the boolean generator    \n",
    "    boolean_generator = logictools_olay.boolean_generator\n",
    "    boolean_generator.reset()\n",
    "    boolean_generator.setup([function])\n",
    "    boolean_generator.run()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "skip"
    }
   },
   "source": [
    "# Logic function widgets\n",
    "\n",
    "A simple GUI, made up of *select* widgets will be built to allow logic functions to be created for each LED. Each logic function can be built from any of the four pushbuttons, and any of the available boolean operators "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true,
    "slideshow": {
     "slide_type": "skip"
    }
   },
   "source": [
    "*Output* allows an LED to be selected"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "slideshow": {
     "slide_type": "skip"
    }
   },
   "outputs": [],
   "source": [
    "output = widgets.Select(\n",
    "    options=['LED0', 'LED1', 'LED2', 'LED3'],\n",
    "    value='LED0',\n",
    "    description='Select LED',\n",
    "    disabled=False)\n",
    "output.layout.width='400px'"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true,
    "slideshow": {
     "slide_type": "skip"
    }
   },
   "source": [
    "Inputs may be any of the four pushbuttons. \n",
    "The NOT logical operator is also encapsulated with an input, rather than as a seperate logical operator"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "slideshow": {
     "slide_type": "skip"
    }
   },
   "outputs": [],
   "source": [
    "inputs = ['PB0', 'PB1', 'PB2', 'PB3', 'NOT PB0', 'NOT PB1', 'NOT PB2', 'NOT PB3', '-']\n",
    "input0 = widgets.Select(\n",
    "    options=inputs,\n",
    "    value='PB0',\n",
    "    #description=' = ',\n",
    "    disabled=False)\n",
    "\n",
    "input1 = widgets.Select(\n",
    "    options=inputs,\n",
    "    value='PB1',\n",
    "    #description='PB',\n",
    "    disabled=False)\n",
    "\n",
    "input2 = widgets.Select(\n",
    "    options=inputs,\n",
    "    value='-',\n",
    "    #description='PB',\n",
    "    disabled=False)\n",
    "\n",
    "input3 = widgets.Select(\n",
    "    options=inputs,\n",
    "    value='-',\n",
    "    #description='PB',\n",
    "    disabled=False)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true,
    "slideshow": {
     "slide_type": "skip"
    }
   },
   "source": [
    "Logical operators *AND*, *OR* and *XOR* can be selected."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "slideshow": {
     "slide_type": "skip"
    }
   },
   "outputs": [],
   "source": [
    "logic_operators=['AND', 'OR', 'XOR', '-']\n",
    "\n",
    "logic0 = widgets.Select(\n",
    "    options=logic_operators,\n",
    "    value='AND',\n",
    "    disabled=False)\n",
    "\n",
    "logic1 = widgets.Select(\n",
    "    options=logic_operators,\n",
    "    value='-',\n",
    "    disabled=False)\n",
    "\n",
    "logic2 = widgets.Select(\n",
    "    options=logic_operators,\n",
    "    value='-',\n",
    "    disabled=False)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true,
    "slideshow": {
     "slide_type": "skip"
    }
   },
   "source": [
    "Update the boolean generator when there is any change to an input *value*."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "slideshow": {
     "slide_type": "skip"
    }
   },
   "outputs": [],
   "source": [
    "output.observe(update_boolean_generator, names='value')\n",
    "logic0.observe(update_boolean_generator, names='value')\n",
    "logic1.observe(update_boolean_generator, names='value')\n",
    "logic2.observe(update_boolean_generator, names='value')\n",
    "input0.observe(update_boolean_generator, names='value')\n",
    "input1.observe(update_boolean_generator, names='value')\n",
    "input2.observe(update_boolean_generator, names='value')\n",
    "input3.observe(update_boolean_generator, names='value')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "skip"
    }
   },
   "source": [
    "Group all items into a container box, and call the update_boolean_generator() function to initialize the boolean generator."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "slideshow": {
     "slide_type": "skip"
    }
   },
   "outputs": [],
   "source": [
    "items = [output, input0, logic0, input1, logic1, input2, logic2, input3]\n",
    "update_boolean_generator(_)\n",
    "\n",
    "select_led = widgets.Box(items)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "### Make a boolean function \n",
    "\n",
    "Inputs can be **PB0**, **PB1**, **PB2**, **PB3** (and their inverse **NOT PB0**, **NOT PB1** ...) for each of the 4 pushbuttons\n",
    "\n",
    "Outputs can be **LD0**, **LD1**, **LD2**, **LD3** for each of the four LEDs\n",
    "\n",
    "Operations can be \n",
    "* **&** : AND\n",
    "* **|** : OR\n",
    "* **^** : XOR "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "Use the select boxes to select the logic function that will be implemented using Pushbuttons, and LEDs as input and output"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "slideshow": {
     "slide_type": "-"
    }
   },
   "outputs": [],
   "source": [
    "select_led"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "-"
    }
   },
   "source": [
    "Test the logic function by pressing the pushbuttons on the board and check the correct LED lights up."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.0"
  },
  "widgets": {
   "application/vnd.jupyter.widget-state+json": {
    "state": {},
    "version_major": 1,
    "version_minor": 0
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
